using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.IO;
using System.Text;
using System.Diagnostics.CodeAnalysis;
using System.Collections.Generic;

// To simplify the process of finding the toolbox bitmap resource:
// #1 Create an internal class called "resfinder" outside of the root namespace.
// #2 Use "resfinder" in the toolbox bitmap attribute instead of the control name.
// #3 use the "<default namespace>.<resourcename>" string to locate the resource.
// See: http://www.bobpowell.net/toolboxbitmap.htm
internal class resfinder
{
}

namespace WeifenLuo.WinFormsUI.Docking
{
	[SuppressMessage("Microsoft.Naming", "CA1720:AvoidTypeNamesInParameters", MessageId = "0#")]
	public delegate IDockContent DeserializeDockContent(string persistString);

	[LocalizedDescription("DockPanel_Description")]
	[Designer(typeof(System.Windows.Forms.Design.ControlDesigner))]
	[ToolboxBitmap(typeof(resfinder), "WeifenLuo.WinFormsUI.Docking.DockPanel.bmp")]
	[DefaultProperty("DocumentStyle")]
	[DefaultEvent("ActiveContentChanged")]
	public partial class DockPanel : Panel
	{
		private FocusManagerImpl m_focusManager;
		private DockPanelExtender m_extender;
		private DockPaneCollection m_panes;
		private FloatWindowCollection m_floatWindows;
		private AutoHideWindowControl m_autoHideWindow;
		private DockWindowCollection m_dockWindows;
		private DockContent m_dummyContent;
		private Control m_dummyControl;

		public DockPanel()
		{
			m_focusManager = new FocusManagerImpl(this);
			m_extender = new DockPanelExtender(this);
			m_panes = new DockPaneCollection();
			m_floatWindows = new FloatWindowCollection();

			SuspendLayout();

			m_autoHideWindow = new AutoHideWindowControl(this);
			m_autoHideWindow.Visible = false;
			SetAutoHideWindowParent();

			m_dummyControl = new DummyControl();
			m_dummyControl.Bounds = new Rectangle(0, 0, 1, 1);
			Controls.Add(m_dummyControl);

			m_dockWindows = new DockWindowCollection(this);
			Controls.AddRange(new Control[]	{
				DockWindows[DockState.Document],
				DockWindows[DockState.DockLeft],
				DockWindows[DockState.DockRight],
				DockWindows[DockState.DockTop],
				DockWindows[DockState.DockBottom]
				});

			m_dummyContent = new DockContent();
			ResumeLayout();
		}

		private AutoHideStripBase m_autoHideStripControl = null;
		internal AutoHideStripBase AutoHideStripControl
		{
			get
			{
				if(m_autoHideStripControl == null)
				{
					m_autoHideStripControl = AutoHideStripFactory.CreateAutoHideStrip(this);
					Controls.Add(m_autoHideStripControl);
				}
				return m_autoHideStripControl;
			}
		}
		internal void ResetAutoHideStripControl()
		{
			if(m_autoHideStripControl != null)
				m_autoHideStripControl.Dispose();

			m_autoHideStripControl = null;
		}

		private void MdiClientHandleAssigned(object sender, EventArgs e)
		{
			SetMdiClient();
			PerformLayout();
		}

		private void MdiClient_Layout(object sender, LayoutEventArgs e)
		{
			if(DocumentStyle != DocumentStyle.DockingMdi)
				return;

			foreach(DockPane pane in Panes)
				if(pane.DockState == DockState.Document)
					pane.SetContentBounds();

			InvalidateWindowRegion();
		}

		private bool m_disposed = false;
		protected override void Dispose(bool disposing)
		{
			lock(this)
			{
				if(!m_disposed && disposing)
				{
					m_focusManager.Dispose();
					if(m_mdiClientController != null)
					{
						m_mdiClientController.HandleAssigned -= new EventHandler(MdiClientHandleAssigned);
						m_mdiClientController.MdiChildActivate -= new EventHandler(ParentFormMdiChildActivate);
						m_mdiClientController.Layout -= new LayoutEventHandler(MdiClient_Layout);
						m_mdiClientController.Dispose();
					}
					FloatWindows.Dispose();
					Panes.Dispose();
					DummyContent.Dispose();

					m_disposed = true;
				}

				base.Dispose(disposing);
			}
		}

		[Browsable(false)]
		public IDockContent ActiveAutoHideContent
		{
			get { return AutoHideWindow.ActiveContent; }
			set { AutoHideWindow.ActiveContent = value; }
		}

		private bool m_allowEndUserDocking = true;
		[LocalizedCategory("Category_Docking")]
		[LocalizedDescription("DockPanel_AllowEndUserDocking_Description")]
		[DefaultValue(true)]
		public bool AllowEndUserDocking
		{
			get { return m_allowEndUserDocking; }
			set { m_allowEndUserDocking = value; }
		}

		private bool m_allowEndUserNestedDocking = true;
		[LocalizedCategory("Category_Docking")]
		[LocalizedDescription("DockPanel_AllowEndUserNestedDocking_Description")]
		[DefaultValue(true)]
		public bool AllowEndUserNestedDocking
		{
			get { return m_allowEndUserNestedDocking; }
			set { m_allowEndUserNestedDocking = value; }
		}

		private DockContentCollection m_contents = new DockContentCollection();
		[Browsable(false)]
		public DockContentCollection Contents
		{
			get { return m_contents; }
		}

		internal DockContent DummyContent
		{
			get { return m_dummyContent; }
		}

		private bool m_rightToLeftLayout = false;
		[DefaultValue(false)]
		[LocalizedCategory("Appearance")]
		[LocalizedDescription("DockPanel_RightToLeftLayout_Description")]
		public bool RightToLeftLayout
		{
			get { return m_rightToLeftLayout; }
			set
			{
				if(m_rightToLeftLayout == value)
					return;

				m_rightToLeftLayout = value;
				foreach(FloatWindow floatWindow in FloatWindows)
					floatWindow.RightToLeftLayout = value;
			}
		}

		protected override void OnRightToLeftChanged(EventArgs e)
		{
			base.OnRightToLeftChanged(e);
			foreach(FloatWindow floatWindow in FloatWindows)
			{
				if(floatWindow.RightToLeft != RightToLeft)
					floatWindow.RightToLeft = RightToLeft;
			}
		}

		private bool m_showDocumentIcon = false;
		[DefaultValue(false)]
		[LocalizedCategory("Category_Docking")]
		[LocalizedDescription("DockPanel_ShowDocumentIcon_Description")]
		public bool ShowDocumentIcon
		{
			get { return m_showDocumentIcon; }
			set
			{
				if(m_showDocumentIcon == value)
					return;

				m_showDocumentIcon = value;
				Refresh();
			}
		}

		[Browsable(false)]
		public DockPanelExtender Extender
		{
			get { return m_extender; }
		}

		public DockPanelExtender.IDockPaneFactory DockPaneFactory
		{
			get { return Extender.DockPaneFactory; }
		}

		public DockPanelExtender.IFloatWindowFactory FloatWindowFactory
		{
			get { return Extender.FloatWindowFactory; }
		}

		internal DockPanelExtender.IDockPaneCaptionFactory DockPaneCaptionFactory
		{
			get { return Extender.DockPaneCaptionFactory; }
		}

		internal DockPanelExtender.IDockPaneStripFactory DockPaneStripFactory
		{
			get { return Extender.DockPaneStripFactory; }
		}

		internal DockPanelExtender.IAutoHideStripFactory AutoHideStripFactory
		{
			get { return Extender.AutoHideStripFactory; }
		}

		[Browsable(false)]
		public DockPaneCollection Panes
		{
			get { return m_panes; }
		}

		internal Rectangle DockArea
		{
			get
			{
				return new Rectangle(DockPadding.Left, DockPadding.Top,
					ClientRectangle.Width - DockPadding.Left - DockPadding.Right,
					ClientRectangle.Height - DockPadding.Top - DockPadding.Bottom);
			}
		}

		private double m_dockBottomPortion = 0.25;
		[LocalizedCategory("Category_Docking")]
		[LocalizedDescription("DockPanel_DockBottomPortion_Description")]
		[DefaultValue(0.25)]
		public double DockBottomPortion
		{
			get { return m_dockBottomPortion; }
			set
			{
				if(value <= 0)
					throw new ArgumentOutOfRangeException("value");

				if(value == m_dockBottomPortion)
					return;

				m_dockBottomPortion = value;

				if(m_dockBottomPortion < 1 && m_dockTopPortion < 1)
				{
					if(m_dockTopPortion + m_dockBottomPortion > 1)
						m_dockTopPortion = 1 - m_dockBottomPortion;
				}

				PerformLayout();
			}
		}

		private double m_dockLeftPortion = 0.25;
		[LocalizedCategory("Category_Docking")]
		[LocalizedDescription("DockPanel_DockLeftPortion_Description")]
		[DefaultValue(0.25)]
		public double DockLeftPortion
		{
			get { return m_dockLeftPortion; }
			set
			{
				if(value <= 0)
					throw new ArgumentOutOfRangeException("value");

				if(value == m_dockLeftPortion)
					return;

				m_dockLeftPortion = value;

				if(m_dockLeftPortion < 1 && m_dockRightPortion < 1)
				{
					if(m_dockLeftPortion + m_dockRightPortion > 1)
						m_dockRightPortion = 1 - m_dockLeftPortion;
				}
				PerformLayout();
			}
		}

		private double m_dockRightPortion = 0.25;
		[LocalizedCategory("Category_Docking")]
		[LocalizedDescription("DockPanel_DockRightPortion_Description")]
		[DefaultValue(0.25)]
		public double DockRightPortion
		{
			get { return m_dockRightPortion; }
			set
			{
				if(value <= 0)
					throw new ArgumentOutOfRangeException("value");

				if(value == m_dockRightPortion)
					return;

				m_dockRightPortion = value;

				if(m_dockLeftPortion < 1 && m_dockRightPortion < 1)
				{
					if(m_dockLeftPortion + m_dockRightPortion > 1)
						m_dockLeftPortion = 1 - m_dockRightPortion;
				}
				PerformLayout();
			}
		}

		private double m_dockTopPortion = 0.25;
		[LocalizedCategory("Category_Docking")]
		[LocalizedDescription("DockPanel_DockTopPortion_Description")]
		[DefaultValue(0.25)]
		public double DockTopPortion
		{
			get { return m_dockTopPortion; }
			set
			{
				if(value <= 0)
					throw new ArgumentOutOfRangeException("value");

				if(value == m_dockTopPortion)
					return;

				m_dockTopPortion = value;

				if(m_dockTopPortion < 1 && m_dockBottomPortion < 1)
				{
					if(m_dockTopPortion + m_dockBottomPortion > 1)
						m_dockBottomPortion = 1 - m_dockTopPortion;
				}
				PerformLayout();
			}
		}

		[Browsable(false)]
		public DockWindowCollection DockWindows
		{
			get { return m_dockWindows; }
		}

		public void UpdateDockWindowZOrder(DockStyle dockStyle, bool fullPanelEdge)
		{
			if(dockStyle == DockStyle.Left)
			{
				if(fullPanelEdge)
					DockWindows[DockState.DockLeft].SendToBack();
				else
					DockWindows[DockState.DockLeft].BringToFront();
			}
			else if(dockStyle == DockStyle.Right)
			{
				if(fullPanelEdge)
					DockWindows[DockState.DockRight].SendToBack();
				else
					DockWindows[DockState.DockRight].BringToFront();
			}
			else if(dockStyle == DockStyle.Top)
			{
				if(fullPanelEdge)
					DockWindows[DockState.DockTop].SendToBack();
				else
					DockWindows[DockState.DockTop].BringToFront();
			}
			else if(dockStyle == DockStyle.Bottom)
			{
				if(fullPanelEdge)
					DockWindows[DockState.DockBottom].SendToBack();
				else
					DockWindows[DockState.DockBottom].BringToFront();
			}
		}

		public int DocumentsCount
		{
			get
			{
				int count = 0;
				foreach(IDockContent content in Documents)
					count++;

				return count;
			}
		}

		public IDockContent[] DocumentsToArray()
		{
			int count = DocumentsCount;
			IDockContent[] documents = new IDockContent[count];
			int i = 0;
			foreach(IDockContent content in Documents)
			{
				documents[i] = content;
				i++;
			}

			return documents;
		}

		public IEnumerable<IDockContent> Documents
		{
			get
			{
				foreach(IDockContent content in Contents)
				{
					if(content.DockHandler.DockState == DockState.Document)
						yield return content;
				}
			}
		}

		private Rectangle DocumentRectangle
		{
			get
			{
				Rectangle rect = DockArea;
				if(DockWindows[DockState.DockLeft].VisibleNestedPanes.Count != 0)
				{
					rect.X += (int)(DockArea.Width * DockLeftPortion);
					rect.Width -= (int)(DockArea.Width * DockLeftPortion);
				}
				if(DockWindows[DockState.DockRight].VisibleNestedPanes.Count != 0)
					rect.Width -= (int)(DockArea.Width * DockRightPortion);
				if(DockWindows[DockState.DockTop].VisibleNestedPanes.Count != 0)
				{
					rect.Y += (int)(DockArea.Height * DockTopPortion);
					rect.Height -= (int)(DockArea.Height * DockTopPortion);
				}
				if(DockWindows[DockState.DockBottom].VisibleNestedPanes.Count != 0)
					rect.Height -= (int)(DockArea.Height * DockBottomPortion);

				return rect;
			}
		}

		private Control DummyControl
		{
			get { return m_dummyControl; }
		}

		[Browsable(false)]
		public FloatWindowCollection FloatWindows
		{
			get { return m_floatWindows; }
		}

		private Size m_defaultFloatWindowSize = new Size(300, 300);
		[Category("Layout")]
		[LocalizedDescription("DockPanel_DefaultFloatWindowSize_Description")]
		public Size DefaultFloatWindowSize
		{
			get { return m_defaultFloatWindowSize; }
			set { m_defaultFloatWindowSize = value; }
		}
		private bool ShouldSerializeDefaultFloatWindowSize()
		{
			return DefaultFloatWindowSize != new Size(300, 300);
		}

		private DocumentStyle m_documentStyle = DocumentStyle.DockingMdi;
		[LocalizedCategory("Category_Docking")]
		[LocalizedDescription("DockPanel_DocumentStyle_Description")]
		[DefaultValue(DocumentStyle.DockingMdi)]
		public DocumentStyle DocumentStyle
		{
			get { return m_documentStyle; }
			set
			{
				if(value == m_documentStyle)
					return;

				if(!Enum.IsDefined(typeof(DocumentStyle), value))
					throw new InvalidEnumArgumentException();

				if(value == DocumentStyle.SystemMdi && DockWindows[DockState.Document].VisibleNestedPanes.Count > 0)
					throw new InvalidEnumArgumentException();

				m_documentStyle = value;

				SuspendLayout(true);

				SetAutoHideWindowParent();
				SetMdiClient();
				InvalidateWindowRegion();

				foreach(IDockContent content in Contents)
				{
					if(content.DockHandler.DockState == DockState.Document)
						content.DockHandler.SetPaneAndVisible(content.DockHandler.Pane);
				}

				PerformMdiClientLayout();

				ResumeLayout(true, true);
			}
		}

		private int GetDockWindowSize(DockState dockState)
		{
			if(dockState == DockState.DockLeft || dockState == DockState.DockRight)
			{
				int width = ClientRectangle.Width - DockPadding.Left - DockPadding.Right;
				int dockLeftSize = m_dockLeftPortion >= 1 ? (int)m_dockLeftPortion : (int)(width * m_dockLeftPortion);
				int dockRightSize = m_dockRightPortion >= 1 ? (int)m_dockRightPortion : (int)(width * m_dockRightPortion);

				if(dockLeftSize < MeasurePane.MinSize)
					dockLeftSize = MeasurePane.MinSize;
				if(dockRightSize < MeasurePane.MinSize)
					dockRightSize = MeasurePane.MinSize;

				if(dockLeftSize + dockRightSize > width - MeasurePane.MinSize)
				{
					int adjust = (dockLeftSize + dockRightSize) - (width - MeasurePane.MinSize);
					dockLeftSize -= adjust / 2;
					dockRightSize -= adjust / 2;
				}

				return dockState == DockState.DockLeft ? dockLeftSize : dockRightSize;
			}
			else if(dockState == DockState.DockTop || dockState == DockState.DockBottom)
			{
				int height = ClientRectangle.Height - DockPadding.Top - DockPadding.Bottom;
				int dockTopSize = m_dockTopPortion >= 1 ? (int)m_dockTopPortion : (int)(height * m_dockTopPortion);
				int dockBottomSize = m_dockBottomPortion >= 1 ? (int)m_dockBottomPortion : (int)(height * m_dockBottomPortion);

				if(dockTopSize < MeasurePane.MinSize)
					dockTopSize = MeasurePane.MinSize;
				if(dockBottomSize < MeasurePane.MinSize)
					dockBottomSize = MeasurePane.MinSize;

				if(dockTopSize + dockBottomSize > height - MeasurePane.MinSize)
				{
					int adjust = (dockTopSize + dockBottomSize) - (height - MeasurePane.MinSize);
					dockTopSize -= adjust / 2;
					dockBottomSize -= adjust / 2;
				}

				return dockState == DockState.DockTop ? dockTopSize : dockBottomSize;
			}
			else
				return 0;
		}

		protected override void OnLayout(LayoutEventArgs levent)
		{
			SuspendLayout(true);

			AutoHideStripControl.Bounds = ClientRectangle;

			CalculateDockPadding();

			DockWindows[DockState.DockLeft].Width = GetDockWindowSize(DockState.DockLeft);
			DockWindows[DockState.DockRight].Width = GetDockWindowSize(DockState.DockRight);
			DockWindows[DockState.DockTop].Height = GetDockWindowSize(DockState.DockTop);
			DockWindows[DockState.DockBottom].Height = GetDockWindowSize(DockState.DockBottom);

			AutoHideWindow.Bounds = GetAutoHideWindowBounds(AutoHideWindowRectangle);

			DockWindows[DockState.Document].BringToFront();
			AutoHideWindow.BringToFront();

			base.OnLayout(levent);

			if(DocumentStyle == DocumentStyle.SystemMdi && MdiClientExists)
			{
				SetMdiClientBounds(SystemMdiClientBounds);
				InvalidateWindowRegion();
			}
			else if(DocumentStyle == DocumentStyle.DockingMdi)
				InvalidateWindowRegion();

			ResumeLayout(true, true);
		}

		internal Rectangle GetTabStripRectangle(DockState dockState)
		{
			return AutoHideStripControl.GetTabStripRectangle(dockState);
		}

		protected override void OnPaint(PaintEventArgs e)
		{
			base.OnPaint(e);

			Graphics g = e.Graphics;
			g.FillRectangle(SystemBrushes.AppWorkspace, ClientRectangle);
		}

		internal void AddContent(IDockContent content)
		{
			if(content == null)
				throw (new ArgumentNullException());

			if(!Contents.Contains(content))
			{
				Contents.Add(content);
				OnContentAdded(new DockContentEventArgs(content));
			}
		}

		internal void AddPane(DockPane pane)
		{
			if(Panes.Contains(pane))
				return;

			Panes.Add(pane);
		}

		internal void AddFloatWindow(FloatWindow floatWindow)
		{
			if(FloatWindows.Contains(floatWindow))
				return;

			FloatWindows.Add(floatWindow);
		}

		private void CalculateDockPadding()
		{
			DockPadding.All = 0;

			int height = AutoHideStripControl.MeasureHeight();

			if(AutoHideStripControl.GetNumberOfPanes(DockState.DockLeftAutoHide) > 0)
				DockPadding.Left = height;
			if(AutoHideStripControl.GetNumberOfPanes(DockState.DockRightAutoHide) > 0)
				DockPadding.Right = height;
			if(AutoHideStripControl.GetNumberOfPanes(DockState.DockTopAutoHide) > 0)
				DockPadding.Top = height;
			if(AutoHideStripControl.GetNumberOfPanes(DockState.DockBottomAutoHide) > 0)
				DockPadding.Bottom = height;
		}

		internal void RemoveContent(IDockContent content)
		{
			if(content == null)
				throw (new ArgumentNullException());

			if(Contents.Contains(content))
			{
				Contents.Remove(content);
				OnContentRemoved(new DockContentEventArgs(content));
			}
		}

		internal void RemovePane(DockPane pane)
		{
			if(!Panes.Contains(pane))
				return;

			Panes.Remove(pane);
		}

		internal void RemoveFloatWindow(FloatWindow floatWindow)
		{
			if(!FloatWindows.Contains(floatWindow))
				return;

			FloatWindows.Remove(floatWindow);
		}

		public void SetPaneIndex(DockPane pane, int index)
		{
			int oldIndex = Panes.IndexOf(pane);
			if(oldIndex == -1)
				throw (new ArgumentException(Strings.DockPanel_SetPaneIndex_InvalidPane));

			if(index < 0 || index > Panes.Count - 1)
				if(index != -1)
					throw (new ArgumentOutOfRangeException(Strings.DockPanel_SetPaneIndex_InvalidIndex));

			if(oldIndex == index)
				return;
			if(oldIndex == Panes.Count - 1 && index == -1)
				return;

			Panes.Remove(pane);
			if(index == -1)
				Panes.Add(pane);
			else if(oldIndex < index)
				Panes.AddAt(pane, index - 1);
			else
				Panes.AddAt(pane, index);
		}

		public void SuspendLayout(bool allWindows)
		{
			FocusManager.SuspendFocusTracking();
			SuspendLayout();
			if(allWindows)
				SuspendMdiClientLayout();
		}

		public void ResumeLayout(bool performLayout, bool allWindows)
		{
			FocusManager.ResumeFocusTracking();
			ResumeLayout(performLayout);
			if(allWindows)
				ResumeMdiClientLayout(performLayout);
		}

		internal Form ParentForm
		{
			get
			{
				if(!IsParentFormValid())
					throw new InvalidOperationException(Strings.DockPanel_ParentForm_Invalid);

				return GetMdiClientController().ParentForm;
			}
		}

		private bool IsParentFormValid()
		{
			if(DocumentStyle == DocumentStyle.DockingSdi || DocumentStyle == DocumentStyle.DockingWindow)
				return true;

			if(!MdiClientExists)
				GetMdiClientController().RenewMdiClient();

			return (MdiClientExists);
		}

		protected override void OnParentChanged(EventArgs e)
		{
			SetAutoHideWindowParent();
			GetMdiClientController().ParentForm = (this.Parent as Form);
			base.OnParentChanged(e);
		}

		private void SetAutoHideWindowParent()
		{
			Control parent;
			if(DocumentStyle == DocumentStyle.DockingMdi ||
					DocumentStyle == DocumentStyle.SystemMdi)
				parent = this.Parent;
			else
				parent = this;
			if(AutoHideWindow.Parent != parent)
			{
				AutoHideWindow.Parent = parent;
				AutoHideWindow.BringToFront();
			}
		}

		protected override void OnVisibleChanged(EventArgs e)
		{
			base.OnVisibleChanged(e);

			if(Visible)
				SetMdiClient();
		}

		private Rectangle SystemMdiClientBounds
		{
			get
			{
				if(!IsParentFormValid() || !Visible)
					return Rectangle.Empty;

				Rectangle rect = ParentForm.RectangleToClient(RectangleToScreen(DocumentWindowBounds));
				return rect;
			}
		}

		internal Rectangle DocumentWindowBounds
		{
			get
			{
				Rectangle rectDocumentBounds = DisplayRectangle;
				if(DockWindows[DockState.DockLeft].Visible)
				{
					rectDocumentBounds.X += DockWindows[DockState.DockLeft].Width;
					rectDocumentBounds.Width -= DockWindows[DockState.DockLeft].Width;
				}
				if(DockWindows[DockState.DockRight].Visible)
					rectDocumentBounds.Width -= DockWindows[DockState.DockRight].Width;
				if(DockWindows[DockState.DockTop].Visible)
				{
					rectDocumentBounds.Y += DockWindows[DockState.DockTop].Height;
					rectDocumentBounds.Height -= DockWindows[DockState.DockTop].Height;
				}
				if(DockWindows[DockState.DockBottom].Visible)
					rectDocumentBounds.Height -= DockWindows[DockState.DockBottom].Height;

				return rectDocumentBounds;

			}
		}

		private PaintEventHandler m_dummyControlPaintEventHandler = null;
		private void InvalidateWindowRegion()
		{
			if(DesignMode)
				return;

			if(m_dummyControlPaintEventHandler == null)
				m_dummyControlPaintEventHandler = new PaintEventHandler(DummyControl_Paint);

			DummyControl.Paint += m_dummyControlPaintEventHandler;
			DummyControl.Invalidate();
		}

		void DummyControl_Paint(object sender, PaintEventArgs e)
		{
			DummyControl.Paint -= m_dummyControlPaintEventHandler;
			UpdateWindowRegion();
		}

		private void UpdateWindowRegion()
		{
			if(this.DocumentStyle == DocumentStyle.DockingMdi)
				UpdateWindowRegion_ClipContent();
			else if(this.DocumentStyle == DocumentStyle.DockingSdi ||
				this.DocumentStyle == DocumentStyle.DockingWindow)
				UpdateWindowRegion_FullDocumentArea();
			else if(this.DocumentStyle == DocumentStyle.SystemMdi)
				UpdateWindowRegion_EmptyDocumentArea();
		}

		private void UpdateWindowRegion_FullDocumentArea()
		{
			SetRegion(null);
		}

		private void UpdateWindowRegion_EmptyDocumentArea()
		{
			Rectangle rect = DocumentWindowBounds;
			SetRegion(new Rectangle[] { rect });
		}

		private void UpdateWindowRegion_ClipContent()
		{
			int count = 0;
			foreach(DockPane pane in this.Panes)
			{
				if(!pane.Visible || pane.DockState != DockState.Document)
					continue;

				count++;
			}

			if(count == 0)
			{
				SetRegion(null);
				return;
			}

			Rectangle[] rects = new Rectangle[count];
			int i = 0;
			foreach(DockPane pane in this.Panes)
			{
				if(!pane.Visible || pane.DockState != DockState.Document)
					continue;

				rects[i] = RectangleToClient(pane.RectangleToScreen(pane.ContentRectangle));
				i++;
			}

			SetRegion(rects);
		}

		private Rectangle[] m_clipRects = null;
		private void SetRegion(Rectangle[] clipRects)
		{
			if(!IsClipRectsChanged(clipRects))
				return;

			m_clipRects = clipRects;

			if(m_clipRects == null || m_clipRects.GetLength(0) == 0)
				Region = null;
			else
			{
				Region region = new Region(new Rectangle(0, 0, this.Width, this.Height));
				foreach(Rectangle rect in m_clipRects)
					region.Exclude(rect);
				Region = region;
			}
		}

		private bool IsClipRectsChanged(Rectangle[] clipRects)
		{
			if(clipRects == null && m_clipRects == null)
				return false;
			else if((clipRects == null) != (m_clipRects == null))
				return true;

			foreach(Rectangle rect in clipRects)
			{
				bool matched = false;
				foreach(Rectangle rect2 in m_clipRects)
				{
					if(rect == rect2)
					{
						matched = true;
						break;
					}
				}
				if(!matched)
					return true;
			}

			foreach(Rectangle rect2 in m_clipRects)
			{
				bool matched = false;
				foreach(Rectangle rect in clipRects)
				{
					if(rect == rect2)
					{
						matched = true;
						break;
					}
				}
				if(!matched)
					return true;
			}
			return false;
		}

		private static readonly object ContentAddedEvent = new object();
		[LocalizedCategory("Category_DockingNotification")]
		[LocalizedDescription("DockPanel_ContentAdded_Description")]
		public event EventHandler<DockContentEventArgs> ContentAdded
		{
			add { Events.AddHandler(ContentAddedEvent, value); }
			remove { Events.RemoveHandler(ContentAddedEvent, value); }
		}
		protected virtual void OnContentAdded(DockContentEventArgs e)
		{
			EventHandler<DockContentEventArgs> handler = (EventHandler<DockContentEventArgs>)Events[ContentAddedEvent];
			if(handler != null)
				handler(this, e);
		}

		private static readonly object ContentRemovedEvent = new object();
		[LocalizedCategory("Category_DockingNotification")]
		[LocalizedDescription("DockPanel_ContentRemoved_Description")]
		public event EventHandler<DockContentEventArgs> ContentRemoved
		{
			add { Events.AddHandler(ContentRemovedEvent, value); }
			remove { Events.RemoveHandler(ContentRemovedEvent, value); }
		}
		protected virtual void OnContentRemoved(DockContentEventArgs e)
		{
			EventHandler<DockContentEventArgs> handler = (EventHandler<DockContentEventArgs>)Events[ContentRemovedEvent];
			if(handler != null)
				handler(this, e);
		}
	}
}